package com.lei2j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.filter.ratelimit.PrincipalNameKeyResolver;
import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@SpringBootApplication
@RestController
public class GateWayApplication {

    @Autowired
    private ApplicationContext applicationContext;

    public static void main(String[] args) {
        SpringApplication.run(GateWayApplication.class,args);
    }

    @Bean
    public RouteLocator buildRouter(RouteLocatorBuilder builder){
        RouteLocatorBuilder.Builder routes = builder.routes();
        return routes
                /*.route(f->
                        //判断满足条件，after实质也是一个predicate,如果有多个后者覆盖前者
                        f.after(ZonedDateTime.of(1900,5,1,0,0,0,0, ZoneId.of("+8")))
                        //negate用于将断言条件反转
                        .uri("http://localhost:8802")
//                        .predicate(p->{
//                             System.out.println("predicate");
//                             return false;
//                         })
                        //过滤器链
                        .filter((s,chain)->{
                            System.out.println("after filter");
                            System.out.println(s.getAttributes());
                            return chain.filter(s);

                        })
                        .id("after_route")
                        .order(2)
                )
                .route(p->p.cookie("test","[a-z0-9A-Z]+")
                           .uri("http://localhost:8802")
                           .id("cookie_route")
                           .filter((g,chain)->{
                               System.out.println("cookie filter");
                               return chain.filter(g);}
                           )
                           .order(1)
                )*/
                /*.route(p->p.remoteAddr("192.168.0.1/24")
                        //url("lb://服务名称:port"),lb为负载均衡
                        .uri("http://localhost:8802")
                        .filter((g, chain) -> {
                            System.out.println("remoteAddr filter");
                            return chain.filter(g);
                        })
                        .id("remoteAddr_route")
                        .order(1)
                )*/
                .route("redirect", p -> p.path("/redirect")
                        .filters(gw -> gw.redirect(301, "https://www.baidu.com"))
                        .uri("http://localhost:8802")
                )
                .route("hystrix_route",
                        p->p.path("/test/**")
                                .filters(gf->gf
                                            .removeRequestHeader("Cache-Control")
                                            .removeResponseHeader("X-RateLimit-Burst-Capacity")
                                            //已/test/foo开始的路径将被设置为/fallback
//                                            .rewritePath("/test/foo/(.*)","/fallback")
//                                            .rewriteResponseHeader("Content-Type","text/.*","application/json")
                                                //使用Spring Session时使用
//                                            .saveSession()
                                            //将路径重新设置为/test
//                                            .setPath("/test")
                                            .setResponseHeader("test","1")
                                            .requestRateLimiter(config ->{
                                                RedisRateLimiter redisRateLimiter = new RedisRateLimiter(2, 2);
                                                redisRateLimiter.setApplicationContext(applicationContext);
                                                config
                                                 .setRateLimiter(redisRateLimiter)
                                                 .setStatusCode(HttpStatus.SERVICE_UNAVAILABLE)
                                                 //以路径限流
                                                 .setKeyResolver(sw->Mono.justOrEmpty(sw.getRequest().getURI().getPath()));
//                                                .setKeyResolver(sw->Mono.justOrEmpty(sw.getRequest().getQueryParams().getFirst("test")));
                                            })
                                            .hystrix(config -> config.setName("hy").setFallbackUri("forward:/fallback")))
                                .uri("ib://client")
                )
                .route(p->p.path("/fallback")
                        .filters(gf->gf.fallbackHeaders(config->config.setExecutionExceptionMessageHeaderName("Test" +
                                "-Header")))
                        .uri("http://localhost:8802")
                        .id("hystrix_fallback")
                )
        .build();
    }

    /*@RequestMapping("/fallback")
    public Mono fallback(){
        return Mono.just("fail");
    }*/
}
